package com.example;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;

/**
 * @ClassName LongAdderTest
 * @Description TODO
 * @Author: XMK
 * @Date: 2021/4/14 11:48
 * @Version: 1.0
 */
public class LongAdderTest {


    public static void main(String[] args) {

        testLongAdder(10, 100_000_000);
        testAtomicLong(10, 100_000_000);
//        testLongAdder(20, 100_000_000);
//        testAtomicLong(20, 100_000_000);
//        testLongAdder(50, 100_000_000);
//        testAtomicLong(50, 100_000_000);
    }

    private static void testLongAdder(int nThreads, int nTimes) {

        LongAdder adder = new LongAdder();
        List<Thread> threads = new ArrayList<>();

        for (int i = 0; i < nThreads; i++) {
            threads.add(new Thread(() -> {
                for (int j = 0; j < nTimes; j++) {
                    adder.increment();
                }
            }));
        }
        long start = System.nanoTime();

        threads.forEach(Thread::start);
        threads.forEach(thread -> {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        long edn = System.nanoTime();

        System.out.println(nThreads + " threads," + nTimes + " times, LongAdder cost:" + (edn - start) / 1000 / 1000 + ", res:" + adder.longValue());

    }

    private static void testAtomicLong(int nThreads, int nTimes) {

        AtomicLong adder = new AtomicLong();

        List<Thread> threads = new ArrayList<>();

        for (int i = 0; i < nThreads; i++) {
            threads.add(new Thread(() -> {
                for (int j = 0; j < nTimes; j++) {
                    adder.incrementAndGet();
                }
            }));
        }
        long start = System.nanoTime();

        threads.forEach(Thread::start);
        threads.forEach(thread -> {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        long edn = System.nanoTime();

        System.out.println(nThreads + " threads," + nTimes + " times, AtomicLong cost:" + (edn - start) / 1000 / 1000 + ", res:" + adder.longValue());

    }


}
